namespace Radar
{
    using System;
    using System.Linq;

    internal static class TypeResolver
    {
        public static Type TryGetImplementation(string key)
        {
            if (string.IsNullOrEmpty(key)) throw new ArgumentNullException("key");

            var serviceType = Type.GetType(key, false);

            if (serviceType == null)
            {
                var message = string.Format("No type could be found by key '{0}'", key);
                throw new TypeResolveException(message);
            }

            return TryGetImplementation(serviceType);
        }

        public static Type TryGetImplementation(Type serviceType)
        {
            if (serviceType == null) throw new ArgumentNullException("serviceType");

            if (serviceType.IsAbstract && serviceType.IsSealed)
            {
                var message = string.Format("Type '{0}' seems to be static - cannot create instance of it.", serviceType);
                throw new TypeResolveException(message);
            }

            var implementation = AppDomain.CurrentDomain
                .GetAssemblies()
                .SelectMany(x => x.GetTypes())
                .FirstOrDefault(t => Implements(serviceType, t));

            if (implementation == null)
            {
                var message = string.Format("Could not find any implementation of '{0}'.", serviceType);
                throw new TypeResolveException(message);
            }

            return implementation;
        }

        private static bool Implements(Type serviceType, Type type)
        {
            return !type.IsAbstract
                   && serviceType.IsAssignableFrom(type);
        }
    }
}